﻿namespace TestTool.GUI.Utils
{
    using System;
    using System.Runtime.CompilerServices;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using TestTool.HttpTransport.Interfaces;
    using TestTool.Proxies.Onvif;

    internal class MediaServiceProvider : BaseServiceProvider<MediaClient, Media>
    {
        public const string TestMediaProfileName = "TestMediaProfile";

        public event AudioEncoderConfigOptionsReceived OnAudioEncoderConfigOptionsReceived;

        public event AudioEncoderConfigurationReceived OnAudioEncoderConfigurationReceived;

        public event AudioSourceConfigurationsReceived OnAudioSourceConfigurationsReceived;

        public event MediaUriReceived OnMediaUriReceived;

        public event ProfilesReceived OnProfilesReceived;

        public event PTZConfigurationAdded OnPTZConfigurationAdded;

        public event VideoEncoderConfigOptionsReceived OnVideoEncoderConfigOptionsReceived;

        public event VideoEncoderConfigurationReceived OnVideoEncoderConfigurationReceived;

        public event VideoSourceConfigurationsReceived OnVideoSourceConfigurationsReceived;

        public MediaServiceProvider(string serviceAddress, int messageTimeout) : base(serviceAddress, messageTimeout)
        {
            base.EnableLogResponse = true;
        }

        public void AddPTZConfiguration(string profile, string configuration)
        {
            base.RunInBackground(delegate {
                this.Client.AddPTZConfiguration(profile, configuration);
                if (this.OnPTZConfigurationAdded != null)
                {
                    this.OnPTZConfigurationAdded(profile, configuration);
                }
            });
        }

        protected void ConfigureProfile(Profile profile, VideoSourceConfiguration videoSourceConfig, VideoEncoderConfiguration videoEncoderConfig, AudioSourceConfiguration audioSourceConfig, AudioEncoderConfiguration audioEncoderConfig)
        {
            if ((profile.VideoSourceConfiguration != null) && (profile.VideoSourceConfiguration.token != videoSourceConfig.token))
            {
                base.Client.RemoveVideoSourceConfiguration(profile.token);
                profile.VideoSourceConfiguration = null;
            }
            if (profile.VideoSourceConfiguration == null)
            {
                base.Client.AddVideoSourceConfiguration(profile.token, videoSourceConfig.token);
            }
            if ((profile.VideoEncoderConfiguration != null) && (profile.VideoEncoderConfiguration.token != videoEncoderConfig.token))
            {
                base.Client.RemoveVideoEncoderConfiguration(profile.token);
                profile.VideoEncoderConfiguration = null;
            }
            if (profile.VideoEncoderConfiguration == null)
            {
                base.Client.AddVideoEncoderConfiguration(profile.token, videoEncoderConfig.token);
            }
            base.Client.SetVideoEncoderConfiguration(videoEncoderConfig, false);
            if ((profile.AudioSourceConfiguration != null) && ((audioSourceConfig == null) || (profile.AudioSourceConfiguration.token != audioSourceConfig.token)))
            {
                base.Client.RemoveAudioSourceConfiguration(profile.token);
                profile.AudioSourceConfiguration = null;
            }
            if ((profile.AudioSourceConfiguration == null) && (audioSourceConfig != null))
            {
                base.Client.AddAudioSourceConfiguration(profile.token, audioSourceConfig.token);
            }
            if ((profile.AudioEncoderConfiguration != null) && ((audioEncoderConfig == null) || (profile.AudioEncoderConfiguration.token != audioEncoderConfig.token)))
            {
                base.Client.RemoveAudioEncoderConfiguration(profile.token);
                profile.AudioEncoderConfiguration = null;
            }
            if (audioEncoderConfig != null)
            {
                if ((profile.AudioEncoderConfiguration == null) && (audioEncoderConfig != null))
                {
                    base.Client.AddAudioEncoderConfiguration(profile.token, audioEncoderConfig.token);
                }
                base.Client.SetAudioEncoderConfiguration(audioEncoderConfig, false);
            }
        }

        public override MediaClient CreateClient(Binding binding, EndpointAddress address)
        {
            return new MediaClient(binding, address);
        }

        protected Profile CreateProfile(string profileName)
        {
            return base.Client.CreateProfile(profileName, null);
        }

        public void GetAudioEncoderConfigOptions(string config)
        {
            base.RunInBackground(delegate {
                AudioEncoderConfigurationOptions options = this.Client.GetAudioEncoderConfigurationOptions(config, null);
                if (this.OnAudioEncoderConfigOptionsReceived != null)
                {
                    this.OnAudioEncoderConfigOptionsReceived(options);
                }
            });
        }

        public void GetAudioEncoderConfigurations()
        {
            base.RunInBackground(delegate {
                AudioEncoderConfiguration[] configs = base.Client.GetAudioEncoderConfigurations();
                if (this.OnAudioEncoderConfigurationReceived != null)
                {
                    this.OnAudioEncoderConfigurationReceived(configs);
                }
            });
        }

        public void GetAudioSourceConfigurations()
        {
            base.RunInBackground(delegate {
                AudioSourceConfiguration[] configs = base.Client.GetAudioSourceConfigurations();
                if (this.OnAudioSourceConfigurationsReceived != null)
                {
                    this.OnAudioSourceConfigurationsReceived(configs);
                }
            });
        }

        public void GetMediaUri()
        {
            base.RunInBackground(delegate {
                Profile videoProfile = this.GetVideoProfile();
                if (videoProfile == null)
                {
                    throw new Exception("Profile with video source encoder configuration not found");
                }
                StreamSetup streamSetup = new StreamSetup {
                    Transport = new Transport()
                };
                streamSetup.Transport.Protocol = TransportProtocol.UDP;
                streamSetup.Stream = StreamType.RTPUnicast;
                MediaUri uri = base.Client.GetStreamUri(streamSetup, videoProfile.token);
                if (this.OnMediaUriReceived != null)
                {
                    this.OnMediaUriReceived(uri, videoProfile.VideoEncoderConfiguration, null);
                }
            });
        }

        public void GetMediaUri(Profile profile, TransportProtocol protocol)
        {
            base.RunInBackground(delegate {
                StreamSetup streamSetup = new StreamSetup {
                    Transport = new Transport()
                };
                streamSetup.Transport.Protocol = protocol;
                streamSetup.Stream = StreamType.RTPUnicast;
                MediaUri uri = this.Client.GetStreamUri(streamSetup, profile.token);
                if (this.OnMediaUriReceived != null)
                {
                    this.OnMediaUriReceived(uri, profile.VideoEncoderConfiguration, profile.AudioEncoderConfiguration);
                }
            });
        }

        public void GetMediaUri(Profile profile, VideoSourceConfiguration videoSourceConfig, VideoEncoderConfiguration videoEncoderConfig, AudioSourceConfiguration audioSourceConfig, AudioEncoderConfiguration audioEncoderConfig, TransportProtocol protocol)
        {
            base.RunInBackground(delegate {
                if (profile == null)
                {
                    profile = this.CreateProfile("TestMediaProfile");
                }
                this.ConfigureProfile(profile, videoSourceConfig, videoEncoderConfig, audioSourceConfig, audioEncoderConfig);
                StreamSetup streamSetup = new StreamSetup {
                    Transport = new Transport()
                };
                streamSetup.Transport.Protocol = protocol;
                streamSetup.Stream = StreamType.RTPUnicast;
                MediaUri uri = this.Client.GetStreamUri(streamSetup, profile.token);
                if (this.OnMediaUriReceived != null)
                {
                    this.OnMediaUriReceived(uri, videoEncoderConfig, audioEncoderConfig);
                }
            });
        }

        public void GetProfiles()
        {
            base.RunInBackground(delegate {
                Profile[] profiles = base.Client.GetProfiles();
                if (this.OnProfilesReceived != null)
                {
                    this.OnProfilesReceived(profiles);
                }
            });
        }

        public void GetVideoEncoderConfigOptions(string config)
        {
            base.RunInBackground(delegate {
                VideoEncoderConfigurationOptions options = this.Client.GetVideoEncoderConfigurationOptions(config, null);
                if (this.OnVideoEncoderConfigOptionsReceived != null)
                {
                    this.OnVideoEncoderConfigOptionsReceived(options);
                }
            });
        }

        public void GetVideoEncoderConfigurations()
        {
            base.RunInBackground(delegate {
                VideoEncoderConfiguration[] configs = base.Client.GetVideoEncoderConfigurations();
                if (this.OnVideoEncoderConfigurationReceived != null)
                {
                    this.OnVideoEncoderConfigurationReceived(configs);
                }
            });
        }

        protected Profile GetVideoProfile()
        {
            foreach (Profile profile2 in base.Client.GetProfiles())
            {
                if ((profile2.VideoSourceConfiguration != null) && (profile2.VideoEncoderConfiguration != null))
                {
                    return profile2;
                }
            }
            return null;
        }

        public void GetVideoSourceConfigurations()
        {
            base.RunInBackground(delegate {
                VideoSourceConfiguration[] configs = base.Client.GetVideoSourceConfigurations();
                if (this.OnVideoSourceConfigurationsReceived != null)
                {
                    this.OnVideoSourceConfigurationsReceived(configs);
                }
            });
        }

        public VideoSource[] GetVideoSources()
        {
            Action unsecure = null;
            VideoSource[] sources = null;
            if (base.Security == Security.None)
            {
                if (unsecure == null)
                {
                    unsecure = delegate {
                        sources = this.Client.GetVideoSources();
                    };
                }
                base.ConstructSecurityTolerantAction(unsecure)();
            }
            else
            {
                sources = base.Client.GetVideoSources();
            }
            return sources;
        }

        public delegate void AudioEncoderConfigOptionsReceived(AudioEncoderConfigurationOptions options);

        public delegate void AudioEncoderConfigurationReceived(AudioEncoderConfiguration[] configs);

        public delegate void AudioSourceConfigurationsReceived(AudioSourceConfiguration[] configs);

        public delegate void MediaUriReceived(MediaUri uri, VideoEncoderConfiguration encoder, AudioEncoderConfiguration audio);

        public delegate void ProfilesReceived(Profile[] profiles);

        public delegate void PTZConfigurationAdded(string profile, string config);

        public delegate void VideoEncoderConfigOptionsReceived(VideoEncoderConfigurationOptions options);

        public delegate void VideoEncoderConfigurationReceived(VideoEncoderConfiguration[] configs);

        public delegate void VideoSourceConfigurationsReceived(VideoSourceConfiguration[] configs);
    }
}

